//
//  MasonryAndReactiveObjCViewController.m
//  TestPrj
//
//  Created by 陈晓星 on 2019/7/9.
//  Copyright © 2019 Xing. All rights reserved.
//

#import "ReactiveObjCViewController.h"
#import <Masonry.h>
#import <ReactiveObjC.h>

@interface ReactiveObjCViewController ()
{
    
    dispatch_semaphore_t value_semaphore;
}

@property(nonatomic,strong)UIScrollView *scrollView;

@property(nonatomic,assign)int totalCount;
@property(nonatomic,strong)NSCondition *countCondition;

@property(nonatomic,assign)NSInteger curValue;//


@end

@implementation ReactiveObjCViewController

- (void)loadView {
    
    [super loadView];
    
    _scrollView = [[UIScrollView alloc] init];
    _scrollView.showsVerticalScrollIndicator = NO;
    [self.view addSubview:_scrollView];
    
//    [_scrollView mas_makeConstraints:^(MASConstraintMaker *make) {
//        make.top.equalTo(self.view.mas_top).offset(0);
//        make.bottom.equalTo(self.view.mas_bottom).offset(0);
//        make.left.equalTo(self.view.mas_left).offset(0);
//        make.right.equalTo(self.view.mas_right).offset(0);
//    }];
    [_scrollView mas_makeConstraints:^(MASConstraintMaker *make) {
        make.edges.equalTo(self.view).with.insets(UIEdgeInsetsZero);
    }];
    
    [self addViews];
}

- (void)updateViewConstraints {
    
    [super updateViewConstraints];
    
    //
}

- (void)addViews {
    
    // ======= 测试视图等分
    
    UIView *contentView = [[UIView alloc] init];
    contentView.backgroundColor = [UIColor greenColor];
    [self.scrollView addSubview:contentView];
    
    //UIScrollView中的约束是依赖于contentSize的，所以会比较不一样一些
    //就是要先由子视图才能确定contentSize，
    [contentView mas_makeConstraints:^(MASConstraintMaker *make) {
        make.top.mas_equalTo(20);
        make.left.mas_equalTo(15);
        make.height.mas_equalTo(100);
        make.width.mas_equalTo(self.scrollView.mas_width).multipliedBy(0.9);
        //如果注释掉上一样，换成使用下面的右约束的话是渲染不出视图的
        //make.right.mas_equalTo(15);
    }];
    
    UIControl *subView1 = [[UIControl alloc] init];
    subView1.backgroundColor = [UIColor yellowColor];
    [contentView addSubview:subView1];

    UIControl *subView2 = [[UIControl alloc] init];
    subView2.backgroundColor = [UIColor redColor];
    [contentView addSubview:subView2];

    [subView1 mas_makeConstraints:^(MASConstraintMaker *make) {
        make.left.and.top.equalTo(contentView).offset(10);
        make.bottom.equalTo(contentView).offset(-10);
    }];

    [subView2 mas_makeConstraints:^(MASConstraintMaker *make) {
        make.left.equalTo(subView1.mas_right).offset(10);
        make.top.equalTo(contentView.mas_top).offset(10);
        make.bottom.equalTo(contentView.mas_bottom).offset(-10);
        make.right.equalTo(contentView.mas_right).offset(-10);
        make.width.equalTo(subView1);
    }];
    
    // ======= ReactiveObjC测试
    [[subView1 rac_signalForControlEvents:UIControlEventTouchUpInside] subscribeNext:^(__kindof UIControl * _Nullable x) {
        [self randomColorAction:x];
    }];
    [subView2 addTarget:self action:@selector(randomColorAction:) forControlEvents:UIControlEventTouchUpInside];
    
    // ====== 测试约束变化
    UIView *changeView = [[UIView alloc] init];
    changeView.backgroundColor = [UIColor purpleColor];
    [self.scrollView addSubview:changeView];
    
    [changeView mas_makeConstraints:^(MASConstraintMaker *make) {
        make.left.equalTo(contentView.mas_left);
        make.right.equalTo(contentView.mas_right);
        make.top.equalTo(contentView.mas_bottom).offset(10);
        make.height.mas_equalTo(70);
    }];
    
    UIView *changeView2 = [[UIView alloc] init];
    changeView2.backgroundColor = [UIColor greenColor];
    [self.scrollView addSubview:changeView2];
    [changeView2 mas_makeConstraints:^(MASConstraintMaker *make) {
        make.top.equalTo(changeView.mas_bottom).offset(20);
        make.left.equalTo(changeView.mas_left);
        make.right.equalTo(changeView.mas_right);
        make.height.mas_equalTo(40);
    }];
    
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        [UIView animateWithDuration:0.6 animations:^{
            [changeView mas_updateConstraints:^(MASConstraintMaker *make) {
                make.height.mas_equalTo(120);
            }];
            [changeView.superview layoutIfNeeded];//添加这句才会有动画
        }];
    });
    
    // ========== 测试自适应内容高度
    UIButton *popBtn = [UIButton buttonWithType:UIButtonTypeRoundedRect];
    [self.scrollView addSubview:popBtn];
    [popBtn mas_makeConstraints:^(MASConstraintMaker *make) {
        make.top.equalTo(changeView2.mas_bottom).offset(20);
        make.left.equalTo(changeView2.mas_left);
        make.right.equalTo(changeView2.mas_right);
        make.height.mas_equalTo(44);
    }];
    popBtn.layer.borderColor = [UIColor lightGrayColor].CGColor;
    popBtn.layer.borderWidth = 0.5;
    [popBtn setTitle:@"弹出窗口" forState:UIControlStateNormal];
    [popBtn addTarget:self action:@selector(popAction:) forControlEvents:UIControlEventTouchUpInside];
    
    
    
    
    
    
    // ========== 多线程代码实践
    
//    // ===== 1、pThread
//
//    UIButton *pThreadButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
//    pThreadButton.titleLabel.font = [UIFont systemFontOfSize:15];
//    [pThreadButton setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
//    [pThreadButton addTarget:self action:@selector(pThreadAction) forControlEvents:UIControlEventTouchUpInside];
//    [self.scrollView addSubview:pThreadButton];
//    [pThreadButton mas_makeConstraints:^(MASConstraintMaker *make) {
//        make.centerX.equalTo(self.scrollView);
//        make.top.equalTo(popBtn.mas_bottom).offset(20);
//        make.width.mas_equalTo(100);
//        make.height.mas_equalTo(44);
//    }];
    
    
    // ===== 2、NSThread
    UIButton *NSThreadButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
    NSThreadButton.titleLabel.font = [UIFont systemFontOfSize:15];
    [NSThreadButton setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
    [NSThreadButton setTitle:@"NSThread" forState:UIControlStateNormal];
    [NSThreadButton addTarget:self action:@selector(NSThreadAction) forControlEvents:UIControlEventTouchUpInside];
    [self.scrollView addSubview:NSThreadButton];
    [NSThreadButton mas_makeConstraints:^(MASConstraintMaker *make) {
        make.centerX.equalTo(self.scrollView);
        make.top.equalTo(popBtn.mas_bottom).offset(20);
        make.width.mas_equalTo(100);
        make.height.mas_equalTo(44);
    }];
    
    
    // ===== 3、GCD
    UIButton *GCDButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
    GCDButton.titleLabel.font = [UIFont systemFontOfSize:15];
    [GCDButton setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
    [GCDButton setTitle:@"GCD" forState:UIControlStateNormal];
    [GCDButton addTarget:self action:@selector(GCDAction) forControlEvents:UIControlEventTouchUpInside];
    [self.scrollView addSubview:GCDButton];
    [GCDButton mas_makeConstraints:^(MASConstraintMaker *make) {
        make.centerX.equalTo(self.scrollView);
        make.top.equalTo(NSThreadButton.mas_bottom).offset(20);
        make.width.mas_equalTo(100);
        make.height.mas_equalTo(44);
    }];
    
    
    // ===== 2、NSOperation
    UIButton *NSOperationButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
    NSOperationButton.titleLabel.font = [UIFont systemFontOfSize:15];
    [NSOperationButton setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
    [NSOperationButton setTitle:@"NSOperation" forState:UIControlStateNormal];
    [NSOperationButton addTarget:self action:@selector(NSOperationAction) forControlEvents:UIControlEventTouchUpInside];
    [self.scrollView addSubview:NSOperationButton];
    [NSOperationButton mas_makeConstraints:^(MASConstraintMaker *make) {
        make.centerX.equalTo(self.scrollView);
        make.top.equalTo(GCDButton.mas_bottom).offset(20);
        make.width.mas_equalTo(100);
        make.height.mas_equalTo(44);
    }];
}

- (void)viewDidLoad {
    
    [super viewDidLoad];
    
    [self testCGDThreadActoin];
}

- (void)randomColorAction:(UIControl *)control {
    
    int r = arc4random()%255;
    int g = arc4random()%255;
    int b = arc4random()%255;
    
    control.backgroundColor = [UIColor colorWithRed:r/255.0
                                              green:g/255.0
                                               blue:b/255.0
                                              alpha:1.0];
}

- (void)popAction:(UIButton *)sender {
    
    NSLog(@"%s",__FUNCTION__);
    
    UIControl *control = [[UIControl alloc] initWithFrame:self.view.bounds];
    control.backgroundColor = [UIColor orangeColor];
    control.tag = 10001;
    [control addTarget:self action:@selector(popDismissAction) forControlEvents:UIControlEventTouchUpInside];
    [self.view addSubview:control];
    
    UIView *container = [[UIView alloc] init];
    container.backgroundColor = [UIColor whiteColor];
    [control addSubview:container];
    
    [container mas_makeConstraints:^(MASConstraintMaker *make) {
        make.centerX.equalTo(container.superview.mas_centerX);
        make.centerY.equalTo(container.superview.mas_centerY);
        make.left.equalTo(container.superview.mas_left).offset(80);
        make.right.equalTo(container.superview.mas_right).offset(-80);
    }];
    
    UILabel *label = [[UILabel alloc] init];
    label.textAlignment = NSTextAlignmentCenter;
    label.numberOfLines = 0;
    label.textColor = [UIColor blackColor];
    label.font = [UIFont systemFontOfSize:16];
    label.text = @"你啊大发了afee.kfjadf.aefwefkefefjqelkffj对方空间里发啊发生的飞机啊了房间法俄反恐饥饿疗法份福利为家里附近违法乱纪为发论文科技论文发发了忘记了就放假了微风飞机饿了饭就饿了无机肥料违法分为放假了我就发了我";
    [container addSubview:label];
    
    [label mas_makeConstraints:^(MASConstraintMaker *make) {
        make.top.equalTo(container.mas_top).offset(20);
        make.left.equalTo(container.mas_left).offset(20);
        make.right.equalTo(container.mas_right).offset(-20);
        make.bottom.equalTo(container.mas_bottom).offset(-20);
    }];
}

- (void)popDismissAction {
    
    for (UIView *view in self.view.subviews) {
        if (view.tag == 10001) {
            [view removeFromSuperview];
            break;
        }
    }
}



#pragma mark -
#pragma mark pThread实现异步（C语言实现框架，极少用,新版xcode需要似乎需要引入其他东西才能通过编辑）

//- (void)pThreadAction {
//
//    pthread_t pthread;
//    char *ch = "test";
//    pthread_create(&pthread, NULL, test, ch);
//}
//void * (test)(void *param) {
//    NSLog(@"%s %@",param,[NSThread currentThread]);
//    return NULL;
//}


#pragma mark -
#pragma mark NSThread实现异步

- (void)NSThreadAction {
    
    NSLog(@"在主线程中执行");
    
//    //1.通过alloc init创建
//    NSThread *thread1 = [[NSThread alloc] initWithTarget:self selector:@selector(runNSThread1) object:nil];
//    thread1.name = @"NSThread1";
//    thread1.threadPriority = 0.2;
//    [thread1 start];
//
//    NSThread *thread2 = [[NSThread alloc] initWithTarget:self selector:@selector(runNSThread1) object:nil];
//    thread2.name = @"NSThread2";
//    thread2.threadPriority = 0.6;
//    [thread2 start];
    
//    //2.通过detachNewThreadSelector创建
//    [NSThread detachNewThreadSelector:@selector(runNSThread1) toTarget:self withObject:nil];
    
//    //3.通过performSelectorInBackground创建
//    [self performSelectorInBackground:@selector(runNSThread1) withObject:nil];
    
    //4.测试 锁
    self.totalCount = 50;
    self.countCondition = [[NSCondition alloc] init];//方式二
    for (int i=0; i<3; i++) {
        NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(syncInThreadAction) object:nil];
        thread.name = [NSString stringWithFormat:@"th%d",i];
        [thread start];
    }
}
- (void)runNSThread1 {
    
    NSLog(@"在子线程中执行-NSThread:%@",[NSThread currentThread].name);
    for (int i=0; i<5; i++) {
        NSLog(@"%d",i);
        [NSThread sleepForTimeInterval:1];
    }
}

//测试锁
- (void)syncInThreadAction {
    
    while (true) {
        
//        //方式一
//        @synchronized (self) {
//            if (self.totalCount>0) {
//                [NSThread sleepForTimeInterval:0.2];
//                self.totalCount --;
//                NSLog(@"threadName:%@,count:%d",[NSThread currentThread].name,self.totalCount);
//            } else {
//                break;
//            }
//        }
        
        //方式一
        [self.countCondition lock];
        if (self.totalCount>0) {
            [NSThread sleepForTimeInterval:0.2];
            self.totalCount --;
            NSLog(@"threadName:%@,count:%d",[NSThread currentThread].name,self.totalCount);
        } else {
            break;
        }
        [self.countCondition unlock];
    }
    
}



#pragma mark -
#pragma mark GCD实现异步

- (void)GCDAction {
    
//    dispatch_queue_t queue = dispatch_queue_create("cgd_queue", DISPATCH_QUEUE_CONCURRENT);//DISPATCH_QUEUE_CONCURRENT指定为并行，其他为串行
//    dispatch_queue_t cgd_inactive_queue = dispatch_queue_create("cgd_inactive_queue", DISPATCH_QUEUE_CONCURRENT);
//    dispatch_activate(cgd_inactive_queue);//初始化不可活动，需要dispatch_activate激活
    
    
    
    
//    dispatch_queue_t queue = dispatch_queue_create("cgd_queue", DISPATCH_QUEUE_CONCURRENT);
//    dispatch_sync(queue, ^{
//        for (int i=0; i<10; i++) {
//            sleep(0.3);
//            NSLog(@"1:%d",i);
//        }
//    });//1
//    dispatch_sync(queue, ^{
//        for (int i=0; i<10; i++) {
//            sleep(0.3);
//            NSLog(@"2:%d",i);
//        }
//    });//2
//    dispatch_async(queue, ^{
//        for (int i=0; i<10; i++) {
//            sleep(0.3);
//            NSLog(@"3:%d",i);
//        }
//    });//3
//    dispatch_async(queue, ^{
//        for (int i=0; i<10; i++) {
//            sleep(0.3);
//            NSLog(@"4:%d",i);
//        }
//    });//4
//    // 1 -> 2 -> (3,4)
    
    
    
    
//    //dispatch_once 用户单利或限制只执行一次的代码
//    for (int i=0; i<5; i++) {
//        [self dispatchOnce];
//    }
    
    
    
    
//    //dispatch_apply函数是dispatch_sync函数和Dispatch Group的关联API
//    NSArray *array = @[@"a", @"b", @"c", @"d", @"e", @"f", @"g", @"h", @"i", @"j"];
//    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);//参数1设置优先级
//    dispatch_async(queue, ^{
//
//        /*
//         dispatch_apply函数说明
//         @brief  dispatch_apply函数是dispatch_sync函数和Dispatch Group的关联API
//         该函数按指定的次数将指定的Block追加到指定的Dispatch Queue中,并等到全部的处理执行结束
//
//         @param 10    指定重复次数  指定10次
//         @param queue 追加对象的Dispatch Queue
//         @param index 带有参数的Block, index的作用是为了按执行的顺序区分各个Block
//         */
//        dispatch_apply([array count], queue, ^(size_t index) {
//            NSLog(@"%zu: %@", index, [array objectAtIndex:index]);
//        });
//
//        //在dispatch_async函数中异步执行dispatch_apply函数,模拟dispatch_sync的同步效果
//        dispatch_async(dispatch_get_main_queue(), ^{
//            NSLog(@"回到主线程执行用户界面更新等操作"); //上面dispatch_apply里的代码执行完之后才会执行到这里
//        });
//    });
    
    
    
    
    dispatch_group_t group = dispatch_group_create();//创建队列
    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);

    dispatch_group_async(group, queue, ^{
        for (int i=0; i<3; i++) {
            sleep(0.5);
            NSLog(@"1:%d",i);
        }
    });

    //子线程中执行异步操作的时候，配对使用dispatch_group_enter和dispatch_group_leave，保证dispatch_group_notify的准确定
    dispatch_group_enter(group);
    /*
     调用dispatch_group_enter；
     将block和queue等信息记录到dispatch_continuation_t结构体中，并将它加入到group的链表中；
     _dispatch_continuation_pop执行时会判断任务是否为group，是的话执行完任务再调用dispatch_group_leave以达到信号量的平衡。
     */
    dispatch_group_async(group, queue, ^{

        dispatch_queue_t innerQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
        dispatch_async(innerQueue, ^{
            for (int i=0; i<5; i++) {
                sleep(0.5);
                NSLog(@"2:%d",i);
            }
            /*
             从上面的源代码中我们看到dispatch_group_leave将dispatch_group_t转换成dispatch_semaphore_t后将dsema_value的值原子性加1。
             如果value为LONG_MIN程序crash；如果value等于dsema_orig表示所有任务已完成，调用_dispatch_group_wake唤醒group（_dispatch_group_wake的用于和notify有关，我们会在后面介绍）。
             因为在enter的时候进行了原子性减1操作。所以在leave的时候需要原子性加1。

             void
             dispatch_group_leave(dispatch_group_t dg)
             {
                 dispatch_semaphore_t dsema = (dispatch_semaphore_t)dg;
                 dispatch_atomic_release_barrier();
                 long value = dispatch_atomic_inc2o(dsema, dsema_value);//dsema_value原子性加1
                 if (slowpath(value == LONG_MIN)) {//内存溢出，由于dispatch_group_leave在dispatch_group_enter之前调用
                     DISPATCH_CLIENT_CRASH("Unbalanced call to dispatch_group_leave()");
                 }
                 if (slowpath(value == dsema->dsema_orig)) {//表示所有任务已经完成，唤醒group
                     (void)_dispatch_group_wake(dsema);
                 }
             }
             */
            dispatch_group_leave(group); //没加enter和leave的话，dispatch_group_notify先执行了
        });
        NSLog(@"block2 complete!");
    });

    //子任务执行完毕
    dispatch_group_notify(group, queue, ^{
        NSLog(@"all async block complete!");
    });
}

- (void)dispatchOnce {
    NSLog(@"______dispatchCoce中");
    static dispatch_once_t once;
    dispatch_once(&once, ^{
        NSLog(@"___onced内的代码只执行一次");
    });
}

/// GCD 信号量测试
- (void)testCGDThreadActoin {
    
    //dispatch_semaphore_tGCD中信号量，也可以解决资源抢占问题,
    //支持信号通知和信号等待。每当发送一个信号通知，则信号量+1；每当发送一个等待信号时信号量-1,；
    //如果信号量为0则信号会处于等待状态，直到信号量大于0开始执行。
    value_semaphore = dispatch_semaphore_create(1);
    
    dispatch_queue_t addQueue = dispatch_queue_create("read_in_gcd_thread", DISPATCH_QUEUE_CONCURRENT);
    dispatch_group_t addGroup = dispatch_group_create();
    for (NSInteger i = 0; i < 3; i++) {
        dispatch_group_async(addGroup, addQueue, ^{
            [self addValueAction];
        });
    }
    dispatch_group_notify(addGroup, dispatch_get_main_queue(), ^{
        NSLog(@"加队列执行完毕");
    });
    
    
    
    dispatch_queue_t reduceQueue = dispatch_queue_create("write_in_gcd_thread", DISPATCH_QUEUE_CONCURRENT);
    dispatch_group_t reduceGroup = dispatch_group_create();
    for (NSInteger i = 0; i < 3; i++) {
        dispatch_group_async(reduceGroup, reduceQueue, ^{
            [self reduceValueAction];
        });
    }
    dispatch_group_notify(reduceGroup, dispatch_get_main_queue(), ^{
        NSLog(@"减队列执行完毕");
    });
     
    [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(redValueAction) userInfo:nil repeats:YES];
}
- (void)addValueAction {

    //semaphore：等待信号
    //DISPATCH_TIME_FOREVER：等待时间
    //wait之后信号量-1，为0
    dispatch_semaphore_wait(value_semaphore, DISPATCH_TIME_FOREVER);
    NSLog(@"curValue +++++等待");
    sleep(2);
    self.curValue ++;
    NSLog(@"curValue +++++完毕");
    
    //发送一个信号通知，这时候信号量+1，为1
    dispatch_semaphore_signal(value_semaphore);
}
- (void)reduceValueAction {
    
    dispatch_semaphore_wait(value_semaphore, DISPATCH_TIME_FOREVER);
    NSLog(@"curValue -----等待");
    sleep(2);
    self.curValue --;
    NSLog(@"curValue -----完毕");
    
    //发送一个信号通知，这时候信号量+1，为1
    dispatch_semaphore_signal(value_semaphore);
}
- (void)redValueAction {
    NSLog(@"___value:%d",(int)self.curValue);
}

#pragma mark -
#pragma mark NSOperation实现异步

- (void)NSOperationAction {
    
//    NSInvocationOperation *operation = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(runFunction) object:nil];
////    NSBlockOperation *operation = [NSBlockOperation blockOperationWithBlock:^{
////        [self runFunction];
////    }];
//    [operation start];
    
    
    
    
//    NSOperationQueue *operationQueue=[[NSOperationQueue alloc]init];
//    NSBlockOperation * blockOperation1 = [NSBlockOperation blockOperationWithBlock:^{
//        NSLog(@"进入操作1");
//        sleep(3);
//        NSLog(@"操作1完成");
//    }];
//    NSBlockOperation * blockOperation2 = [NSBlockOperation blockOperationWithBlock:^{
//        NSLog(@"进入依赖操作");
//    }];
//
//    //依赖必须在操作被添加到队列(确切来说应该是被执行)之前设置、否则无效
//    [blockOperation2 addDependency:blockOperation1]; //添加依赖
//
//    [operationQueue addOperation:blockOperation1];
//    [operationQueue addOperation:blockOperation2];
//
//    //依赖在添加进队列之后虽然不能追加。但是可以对某操作进行追加addExecutionBlock、也可以延后操作的执行。
//    //正在执行和完成的 operation，添加操作都会抛异常
//    [blockOperation1 addExecutionBlock:^{
//        NSLog(@"进入追加操作");
//        sleep(5);
//        NSLog(@"追加操作完成");
//    }];
    
    
    
    
    NSOperationQueue *operationQueue=[[NSOperationQueue alloc]init];
    //operationQueue.maxConcurrentOperationCount(1);
    
//    NSBlockOperation *ope1 = [NSBlockOperation blockOperationWithBlock:^{
//        [self runFunction2:1];
//    }];
//    NSBlockOperation *ope2 = [NSBlockOperation blockOperationWithBlock:^{
//        [self runFunction2:2];
//    }];
//    NSBlockOperation *ope3 = [NSBlockOperation blockOperationWithBlock:^{
//        [self runFunction];
//    }];
    //通过制定以block有效地处理的Operaion中的异步执行问题
    CustomOperaion *ope1 = [[CustomOperaion alloc] init];
    ope1.index = 1;
    CustomOperaion *ope2 = [[CustomOperaion alloc] init];
    ope1.index = 2;
    NSBlockOperation *ope3 = [NSBlockOperation blockOperationWithBlock:^{
        [self runFunction];
    }];
    
    [ope3 addDependency:ope2];
    [ope2 addDependency:ope1];
    
    [operationQueue addOperation:ope1];
    [operationQueue addOperation:ope2];
    [operationQueue addOperation:ope3];
}

- (void)runFunction {
    NSLog(@"runFunction1");
}

- (void)runFunction2:(int)index {
    
    dispatch_async(dispatch_get_global_queue(0, 0), ^{
        for (int i=0; i<3; i++) {
            [NSThread sleepForTimeInterval:1];
            NSLog(@"index_%d:%d",index,i);
        }
    });
    NSLog(@"runFunction2");
}

@end





//自定义Operation
@interface CustomOperaion()

@property(nonatomic,assign) BOOL isOver;

@end

@implementation CustomOperaion

- (void)main {
    
    self.isOver = NO;
    dispatch_async(dispatch_get_global_queue(0, 0), ^{
        for (int i=0; i<3; i++) {
            [NSThread sleepForTimeInterval:1];
            NSLog(@"index_%d:%d",(int)self.index,i);
        }
        self.isOver = YES;
    });
    NSLog(@"runFunction2");
    
    while (!self.isOver && !self.cancelled && !self.isFinished) {
        [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];
    }
}

@end
